package com.lonely.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lonely.common.core.domain.BaseEntity;
import com.lonely.system.domain.entity.SysUser;
import com.lonely.common.enums.CommonStatus;
import com.lonely.common.utils.SecurityUtils;
import com.lonely.system.domain.entity.SysUserRole;
import com.lonely.system.domain.dto.role.BindRoleUsersDto;
import com.lonely.system.domain.dto.role.BindUserRoleDto;
import com.lonely.system.domain.dto.user.SysUserRoleNameDto;
import com.lonely.system.domain.vo.system.user.SysUserDetailVo;
import com.lonely.system.mapper.SysUserRoleMapper;
import com.lonely.system.service.ISysRoleService;
import com.lonely.system.service.ISysUserRoleService;
import com.lonely.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: 黄志标
 * @date: 2025/6/3 14:57
 * @description: 用户角色服务实现类
 */
@Service
public class SysUserRoleServiceImpl extends ServiceImpl<SysUserRoleMapper, SysUserRole> implements ISysUserRoleService {

    @Autowired
    private ISysRoleService sysRoleService;

    @Autowired
    private ISysUserService sysUserService;


    /**
     * 获取用户角色信息
     *
     * @param userId
     * @return
     */
    @Override
    public List<SysUserDetailVo.RoleInfo> getRolesByUserId(Long userId) {

        // 获取用户关联的角色信息
        List<SysUserRole> userRoles = super.list(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId));
        if (CollUtil.isEmpty(userRoles)) {
            return new ArrayList<>();
        }

        List<Long> roleIds = userRoles.stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
        return Optional.ofNullable(this.sysRoleService.listByIds(roleIds)).orElse(new ArrayList<>())
                .stream().map(x -> {
                    SysUserDetailVo.RoleInfo roleInfo = new SysUserDetailVo.RoleInfo();
                    roleInfo.setId(x.getId());
                    roleInfo.setRoleName(x.getRoleName());
                    roleInfo.setRemark(x.getRemark());

                    if (x.getAttribution() != null) {
                        SysUser user = this.sysUserService.getById(x.getAttribution());
                        if (user != null) {
                            roleInfo.setAttribution(user.getUserName());
                        }
                    }
                    return roleInfo;
                }).collect(Collectors.toList());
    }

    /**
     * 绑定用户角色关联
     *
     * @param bindUserRoleDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void bindUserRoles(BindUserRoleDto bindUserRoleDto) {
        if (CollUtil.isEmpty(bindUserRoleDto.getRoleIds())) {
            return;
        }

        // 获取传入的角色id中有效的部分
        List<Long> effectiveRoleIds = Optional.ofNullable(this.sysRoleService.listByIds(bindUserRoleDto.getRoleIds())).orElse(new ArrayList<>())
                .stream().filter(x -> Objects.equals(x.getStatus(), CommonStatus.ENABLE.code))
                .map(BaseEntity::getId).collect(Collectors.toList());

        // 获取当前用户已绑定的角色id
        List<Long> alreadyBindRoleIds = super.list(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, bindUserRoleDto.getUserId())).stream()
                .map(SysUserRole::getRoleId).distinct().collect(Collectors.toList());

        // 获取需要进行绑定的角色id集合
        List<Long> bindRoleIds = CollUtil.subtractToList(effectiveRoleIds, alreadyBindRoleIds);
        if (CollUtil.isEmpty(bindRoleIds)) {
            return;
        }

        List<SysUserRole> sysUserRoles = bindRoleIds.stream().map(x -> {
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setUserId(bindUserRoleDto.getUserId());
            sysUserRole.setRoleId(x);
            sysUserRole.setCreateBy(SecurityUtils.getUserId());
            sysUserRole.setUpdateBy(SecurityUtils.getUserId());
            return sysUserRole;
        }).collect(Collectors.toList());
        super.saveBatch(sysUserRoles);
    }

    /**
     * 解除用户角色关联
     *
     * @param unBindUserRoleDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void unBindUserRoles(BindUserRoleDto unBindUserRoleDto) {
        if (CollUtil.isEmpty(unBindUserRoleDto.getRoleIds())) {
            return;
        }
        super.remove(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, unBindUserRoleDto.getUserId())
                .in(SysUserRole::getRoleId, unBindUserRoleDto.getRoleIds()));

    }

    /**
     * 查询用户角色名称映射
     *
     * @param userIds
     * @return
     */
    @Override
    public List<SysUserRoleNameDto> queryUserRoleNames(List<Long> userIds) {
        if (CollUtil.isEmpty(userIds)) {
            return new ArrayList<>();
        }
        return super.getBaseMapper().queryUserRoleNames(userIds);
    }

    /**
     * 绑定角色用户关联
     *
     * @param bindRoleUsersDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void bindRoleUsers(BindRoleUsersDto bindRoleUsersDto) {
        if (CollUtil.isEmpty(bindRoleUsersDto.getUserIds())) {
            return;
        }

        // 获取传入的用户id中有效的部分
        List<Long> effectiveUserIds = Optional.ofNullable(this.sysUserService.listByIds(bindRoleUsersDto.getUserIds())).orElse(new ArrayList<>())
                .stream().filter(x -> Objects.equals(x.getStatus(), CommonStatus.ENABLE.code))
                .map(BaseEntity::getId).collect(Collectors.toList());

        // 获取当前角色已绑定的用户id
        List<Long> alreadyBindUserIds = super.list(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getRoleId, bindRoleUsersDto.getRoleId())).stream()
                .map(SysUserRole::getUserId).distinct().collect(Collectors.toList());

        // 获取需要进行绑定的用户id集合
        List<Long> bindUserIds = CollUtil.subtractToList(effectiveUserIds, alreadyBindUserIds);
        if (CollUtil.isEmpty(bindUserIds)) {
            return;
        }

        List<SysUserRole> sysUserRoles = bindUserIds.stream().map(x -> {
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setUserId(x);
            sysUserRole.setRoleId(bindRoleUsersDto.getRoleId());
            sysUserRole.setCreateBy(SecurityUtils.getUserId());
            sysUserRole.setUpdateBy(SecurityUtils.getUserId());
            return sysUserRole;
        }).collect(Collectors.toList());
        super.saveBatch(sysUserRoles);
    }

    /**
     * 解除角色用户关联
     *
     * @param unBindRoleUsersDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void unBindRoleUsers(BindRoleUsersDto unBindRoleUsersDto) {
        if (CollUtil.isEmpty(unBindRoleUsersDto.getUserIds())) {
            return;
        }
        super.remove(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getRoleId, unBindRoleUsersDto.getRoleId())
                .in(SysUserRole::getUserId, unBindRoleUsersDto.getUserIds()));
    }
}
